//standroom.c used by weiqi...others may hate this format:D
//shaizi-room.c...weiqi, 98/01/17
//allow 坐庄，下注等。

inherit ROOM;

int round = 0; //this indicates how many games processed.
int ask_for_zhuang = 0;

int game_status = 0;
//=0, no game yet.
//=1, zhuang-jia determined.
//=2, zhuang-jia typed "start", begin bet process.
//=3, bet finished...zhuang-jia used "bet ***" to put on money, now game processing.
//return to 0, game finished.
//if zhuang-jia retire, return to 0.

string zhuang_id = "no zhuang"; //zhuang-jia's id.

int total_bet = 0;//total money on table, in unit of silver.

int max_bet ; //max bet each round, determined by zhuang-jia. 

void pay_player(object me, int total);
int pay_out(object me, int total);
int check_silver(object me);
void game_process();
void show_shaizi(object me);
void game_result();
void check_finish(int previous_round);
void check_start(int previous_round);
#include <ansi.h>

void create ()
{
	set ("short",HIR "[" HIY "骰子房" HIR "]" NOR);
	set ("long", @LONG

屋中间摆着一张看起来相当结实的大长条桌(table)，四周围了十
几把靠背木椅。北面墙上有一块牌子(paizi)。
LONG);

	set("item_desc", (["paizi" : "

赌骰子规则：
每一轮有个庄家，输赢只跟庄家比。两粒骰子，成对为大。十点最小。
开赌顺序：
一，确定庄家(用zz或zuozhuang坐庄，retire或rz, rangzhuang让庄)。
二，庄家宣布开盘(start <赌注上限>)。
三，玩家下注(bet或xz, xiazhu)。
四，庄家下注(bet或xz, xiazhu)，至少要押别的玩家的总和。
五，庄家下注就开赌了。

注意事项：
一，赌中不要离开赌场，否则一切损失概不负责。
二，坐庄时要先拿出五两金子的保证金，让庄时退还。非正常丢庄(如
　　中途离开等)保证金自动失去。
三，每一轮从庄家宣布开盘起十分钟之内必须完成，否则取消重来。
　　非庄家所下之注可被退回，而庄家则可能会有损失。
四，如果庄家迟迟不宣布开盘，玩家可用坐庄(zz)指令要求换庄。
　　要求换庄后两分钟内庄家比须宣布开盘，否则丢庄。
五，在下注过程中可用取消(cancel)指令。庄家用此指令则宣布此局无效，
　　大家将赌注取回，庄家非正常丢庄。非庄家用此指令则表示退出此
　　局，赌注可取回。
		\n" ]));
	//for look something.

	set("exits", 
	([ //sizeof() == 4
		//"south" : __DIR__"xiaomuwu",
		//"north" : __DIR__"chufang",
		//"west" : __DIR__"duchang2",
		"east" : __DIR__"clubpoem",
		//"up" : __DIR__"***",
		//"down" : __DIR__"***",
	]));
	
	set("objects", 
	([ //sizeof() == 1
		__DIR__"npc/gongsun" : 1,
	]));


	//set("outdoors", "city");
	set("no_fight", 1);
	set("no_magic", 1);
	
	set("no_clean_up", 1);

	set("no_caishen", 1);

	setup();
}

void init()
{
	object me;

	add_action("do_bet", "bet");
	add_action("do_bet", "xiazhu");
	add_action("do_bet", "xz");

	add_action("do_zuozhuang", "zuozhuang");
	add_action("do_zuozhuang", "zz");

	add_action("do_retire", "retire");
	add_action("do_retire", "rangzhuang");
	add_action("do_retire", "rz");

	add_action("do_start", "start");
	add_action("do_start", "kaipan");
	add_action("do_start", "kp");
	
	add_action("do_cancel", "cancel");

	add_action("do_look", "look");
        add_action ("do_bian","bian");
	//all ppls enter this room, "shaizi/***" got deleted.
	me=this_player();
	if( me->query_temp("shaizi") )
	{
		me->delete_temp("shaizi");
	}
}

int do_bet(string arg)
{
	object me;
	int amount;
	string money;
	object ob;
	int this_bet; //in unit of silver.

	me=this_player();

	if(! arg || sscanf (arg,"%d %s", amount, money) != 2)
		return notify_fail("请使用：bet(或xiazhu, xz) <数目> <货币>\n");

	//check valid money first.
	ob = present (money+"_money", me);
	if(! ob) return notify_fail("你身上没有这种钱。\n");
	if(amount < 1) return notify_fail("想行骗？\n");
	if(amount > ob->query_amount()) return notify_fail("你没这么多钱。\n");
	if(money=="coin") return notify_fail("铜板？还是到大街上去赌吧。\n");

	if(zhuang_id != me->query("id"))
	{//I am not zhuang-jia.
		if(game_status != 2)
			return notify_fail("还没到下注的时候，听庄家吩咐。\n");

		//now let's bet.
		this_bet = amount*ob->query("base_value")/100;
		if( (this_bet + (int)me->query_temp("shaizi/bet_amount")) > max_bet )
			return notify_fail("庄家太穷了，赌不起。换庄家吧。\n");

		total_bet += this_bet;
	
		me->set_temp("shaizi/bet_amount", this_bet + (int)me->query_temp("shaizi/bet_amount"));
		message_vision (sprintf("$N拿出%s%s%s，押在桌子上。\n",
			chinese_number(amount),
			ob->query("base_unit"),
			ob->query("name")),
			me);

		if (amount == ob->query_amount()) destruct (ob);
		else ob->add_amount(-amount);
	}
	else
	{//I am zhuang-jia.
		if(game_status != 2)
			return notify_fail("你现在头脑不清醒，还是别坐庄了。\n");
		if(total_bet == 0)
			return notify_fail("还没人下注呢。等大家都下完了你再下吧。\n");

		//now let's bet.
		this_bet = amount*ob->query("base_value")/100;
		if(this_bet < total_bet)
			return notify_fail("这一轮共下注"+total_bet+"两银子，庄家所押不能少于这个数目。\n");		

		total_bet += this_bet;	
		me->set_temp("shaizi/bet_amount", this_bet + (int)me->query_temp("shaizi/bet_amount"));
		message_vision (sprintf("$N拿出%s%s%s，押在桌子上。\n",
			chinese_number(amount),
			ob->query("base_unit"),
			ob->query("name")),
			me);

		if (amount == ob->query_amount()) destruct (ob);
		else ob->add_amount(-amount);

		message_vision("$N手一压：好！现在开掷，大家一个一个来。\n", me);
		game_status = 3;
				
		call_out("game_process", 1);	
	}	
	return 1;
}

int do_bian(string arg)
{
    tell_object(this_player(), "请不要在骰子房里变来变去。\n");
    return 1;
}


int do_cancel()
{
	//this can only happen in bet process.
	//for zhuang-jia, he does not want continue and lost his zhuang_deposit and 
	//others get money back. 
	//for non_zhuang players, he simply gets his money back.
	object me;
	int i;
	object *inv = all_inventory(this_object());
	me = this_player();

	if(game_status != 2) return notify_fail("现在没有什么需要取消的。\n"); 

	if( me->query_temp("shaizi_cancel_count") > 5 )
		return notify_fail("你最近反悔的次数太多了，赌信已经太差。\n"); 

	if( me->query("id") == zhuang_id )
	{//I am zhuang-jia.
		message_vision("$N起身说道：这一把我赌不下去了，你们把钱拿回去另找人坐庄吧！\n", me);		
		zhuang_id = "no zhuang";
		me->delete_temp("shaizi");

		me->set_temp("shaizi_cancel_count", 1+me->query_temp("shaizi_cancel_count"));

		//give ppls money back.
		for(i=0; i<sizeof(inv); i++)
		{
			if( inv[i]->query_temp("shaizi/bet_amount") > 0 && inv[i]->query("id") != zhuang_id )
			{
				total_bet -=  inv[i]->query_temp("shaizi/bet_amount");
				if(total_bet >= 0)
				{
					pay_player(inv[i], inv[i]->query_temp("shaizi/bet_amount"));
					message_vision("$N起身把放在桌子上的赌注拿了回来。\n", inv[i]);
				}
				else
				{
					message_vision("糟糕！有人在这里偷钱！$N的钱没了。\n", inv[i]);
				}
			}
			if( inv[i]->query_temp("shaizi") ) inv[i]->delete_temp("shaizi");
		}
		zhuang_id = "no zhuang";
		game_status = 0;
		total_bet = 0;
		remove_call_out("check_finish");
	}
	else
	{//if I am not zhuang-jia.
		if( me->query_temp("shaizi/bet_amount") <= 0 ) 
			return notify_fail("你又没下注，在这里起什么哄？\n"); 
			
		total_bet -=  me->query_temp("shaizi/bet_amount");
		if( total_bet >=0 )
		{		
			message_vision("$N起身把放在桌子上的赌注拿了回来。\n", me);
			pay_player(me, me->query_temp("shaizi/bet_amount"));
			me->delete_temp("shaizi");
			me->set_temp("shaizi_cancel_count", 1+me->query_temp("shaizi_cancel_count"));
		}
		else
		{
			message_vision("糟糕！有人在这里偷钱！$N的钱没了。\n", me);
		}
	}
	return 1;
}

int do_zuozhuang()
{
	object me, zhuang;

	int zhuang_deposit = 500; //5 gold.

	me=this_player();

	if (zhuang_id == me->query("id"))
	{
		return notify_fail("你已经是庄家了。\n");
	}
	
	if(game_status == 1 || game_status == 0 )
	{//only in this two case can 换庄
		if(objectp(zhuang=present(zhuang_id, this_object())) )
		{//if the previous zhuang-jia is here.
			//if the zhuang-jia does not "start"...cancel his zhuang.
			if(ask_for_zhuang == 0)
			{
				ask_for_zhuang = 1;
				call_out("check_start", 120, round);
				tell_room(this_object(), me->query("name")+"也想坐庄。如果庄家两分钟内不能开盘(start)，就得让庄了。\n");
			} 
			return notify_fail("已经有庄家了，叫"+zhuang->query("name")+"("+zhuang->query("id")+")让庄吧。\n");	
		}
		else
		{
			if( !pay_out(me, zhuang_deposit) )
				return notify_fail("你没有足够的钱交坐庄保证金。\n");

			me->set_temp("shaizi_zhuang_deposit", 500);
			//note this parameter is not in "shaizi" array.
		
			message_vision("$N拿出一锭金子往桌上一拍，在庄家的位子上坐了下来。\n", me);
			zhuang_id = (string)me->query("id");
			game_status = 1; //zhuang-jia changed.
			return 1;
		}
	}
	else
		return notify_fail("现在还不能换庄。\n");
}

int do_retire()
{
	object me;

	me=this_player();

	if(zhuang_id != me->query("id"))
		return notify_fail("你又不是庄家，让什么让？\n");

	if(game_status == 1 || game_status == 0 )
	{
		message_vision("$N站起来嚷道：这个霉庄我可不坐了！说罢顺手将桌上的保证金揣在怀里。\n", me);
		zhuang_id = "no zhuang";
		game_status = 0;
		pay_player(me, me->query_temp("shaizi_zhuang_deposit"));
		me->delete_temp("shaizi_zhuang_deposit");
		return 1;
	}
	else
	{//not the time to 让庄.
		return notify_fail("想逃？好歹得赌完这一把。\n");
	}
}

int do_start(string arg)
{
	int max_limit = 1000; //1000 gold.
	int min_limit = 10; //10 gold.
	int current_limit;

	object me;

	me=this_player();

	if(zhuang_id != me->query("id"))
		return notify_fail("只有庄家才能开盘。\n");

	if(game_status == 1 || game_status == 0 )
	{
		if(! arg || sscanf (arg,"%d", current_limit) != 1)
			return notify_fail("请使用：start <赌注上限，单位：黄金>\n");

		if(current_limit < min_limit)
			return notify_fail("你也太穷了吧？还是别坐庄了。赌注上限别少于"+chinese_number(min_limit)+"两黄金。\n");
		if(current_limit > max_limit)
			return notify_fail("你也太富了吧？别超过"+chinese_number(max_limit)+"两黄金。\n");

		max_bet = 100*current_limit; //max_bet in silver.
		message_vision("$N手一挥大声叫道：开盘！现在开始下注！\n", me);
		message_vision("$N顿了一下：赌注别超过"+chinese_number(current_limit)+"两黄金。\n", me);

		total_bet = 0;
		game_status = 2; //enter the bet process.
		round++; //we increase this number to indicate a new round of game.
		remove_call_out("check_finish");
		call_out("check_finish", 600, round); 
		//a game must be finished within 10 minutes. 
		return 1;
	}
	else
	{//not the time to 开盘.
		return notify_fail("现在还不能开盘。\n");
	}
}

void check_start(int previous_round)
{
	ask_for_zhuang = 0;//so after this, can ask again...

	if(previous_round != round) return; //it means already started.	

	//now if still in this round.
	if( game_status == 3) return; //game in processing, can do nothing here.

	tell_room(this_object(), "庄家迟迟不开盘，只好换庄了。\n");
	zhuang_id = "no zhuang";
	game_status = 0;
	total_bet = 0;
}

void check_finish(int previous_round)
{
	int i;
	object *inv = all_inventory(this_object());

	if(previous_round != round) return; //it means already finished.
	
	//now if still in this round.
	if( game_status == 3) return; //game in processing, can do nothing here.

	//here we need cancel the game.
	//give money back to all players except zhuang-jia, cuz this is his/her fault.
	tell_room(this_object(), "这一局迟迟未能完成，只好取消重来了。\n");
	for(i=0; i<sizeof(inv); i++)
	{
		if( inv[i]->query_temp("shaizi/bet_amount") > 0 && inv[i]->query("id") != zhuang_id )
		{
			total_bet -=  inv[i]->query_temp("shaizi/bet_amount");
			if(total_bet >= 0)
			{
				pay_player(inv[i], inv[i]->query_temp("shaizi/bet_amount"));
				message_vision("$N起身把放在桌子上的赌注拿了回来。\n", inv[i]);
			}
			else
			{
				message_vision("糟糕！有人在这里偷钱！$N的钱没了。\n", inv[i]);
			}
		}
		if( inv[i]->query_temp("shaizi") ) inv[i]->delete_temp("shaizi");
	}

	zhuang_id = "no zhuang";
	game_status = 0;
	total_bet = 0;
}

void game_process()
{
	int i, j;
	object *inv = all_inventory(this_object());
	
	j=0;
	for(i=0; i<sizeof(inv); i++)
	{
		if( (int)inv[i]->query_temp("shaizi/bet_amount") > 0 )
		{
			j++;
			call_out("show_shaizi", j*4, inv[i]);
		}
	}

	call_out("game_result", (j+2)*4);	
}

void show_shaizi(object me)
{
	string point_msg;
	string *sha_msg = ({
		"瞪着一对红眼，大喝一声：杀！手中的两粒骰子往桌子上一摔！\n",
		"往手上吹了口气，两粒骰子轻轻一抛．．．\n",
		"微微一笑，两粒骰子往桌子上一滚．．．\n",
		"望空作了个揖：菩萨保佑！两粒骰子战战噤噤地桌上一投．．．\n",
		"拿着两粒骰子，抖足精神：娶老婆生孩子在此一举！\n",
		"衣袖一卷，大声叫道：看我的！\n",
		"咬牙切齿，两粒骰子往桌子上狠狠地一砸．．．\n",
		"满头大汗，自言自语道：六对，六对，该上我家了吧．．．\n",
		"潇洒地作了个四方揖：这把该我赢，看好了．．．\n",
		});

	string *shaizi_msg = ({
"┌───┐\n"+
"│　　　│\n"+
"│　　　│\n"+
"│　　　│\n"+
"└───┘\n", 
"┌───┐\n"+
"│　　　│\n"+
"│　●　│\n"+
"│　　　│\n"+
"└───┘\n", 
"┌───┐\n"+
"│　　　│\n"+
"│●　●│\n"+
"│　　　│\n"+
"└───┘\n", 
"┌───┐\n"+
"│●　　│\n"+
"│　●　│\n"+
"│　　●│\n"+
"└───┘\n", 
"┌───┐\n"+
"│●　●│\n"+
"│　　　│\n"+
"│●　●│\n"+
"└───┘\n", 
"┌───┐\n"+
"│●　●│\n"+
"│　●　│\n"+
"│●　●│\n"+
"└───┘\n", 
"┌───┐\n"+
"│●　●│\n"+
"│●　●│\n"+
"│●　●│\n"+
"└───┘\n",
		});

	if(environment(me) == this_object() || me->query_temp("shaizi/bet_amount") > 0)
	{
		me->set_temp("shaizi/point1", 1+random(6));//first shaizi.
		me->set_temp("shaizi/point2", 1+random(6));//second shaizi.
		if( me->query_temp("shaizi/point1") == me->query_temp("shaizi/point2") && me->query_temp("shaizi/point2") != 0 )
		{
			me->set_temp("shaizi/point",  100+me->query_temp("shaizi/point2"));
			point_msg = chinese_number(me->query_temp("shaizi/point2"))+"对";
		}
		else
		{
			me->set_temp("shaizi/point",  (me->query_temp("shaizi/point1") +me->query_temp("shaizi/point2") )%10);
			point_msg = chinese_number(me->query_temp("shaizi/point"))+"点";
			if(me->query_temp("shaizi/point") == 0)
				point_msg = "蹩十";
		}		

		tell_room (this_object(), me->query("name")+sha_msg[random(sizeof(sha_msg))]);
		tell_room (this_object(), shaizi_msg[(int)me->query_temp("shaizi/point1")]);
		tell_room (this_object(), shaizi_msg[(int)me->query_temp("shaizi/point2")]);
		tell_room (this_object(), "众人齐声叫道："+point_msg+"！\n");
	}
	
}

void game_result()
{
	object zhuang;
	int i, zhuang_point;
	object *inv = all_inventory(this_object());

	if(objectp(zhuang=present(zhuang_id, this_object())) && living(zhuang) )
	{//if the zhuang-jia is here.
		tell_room(this_object(), zhuang->query("name")+"大声宣布：结帐！\n");	
		zhuang_point = zhuang->query_temp("shaizi/point");
	}
	else 
	{
		tell_room(this_object(), "庄家不知道跑到哪里去了。大家都赢了！\n");	
		zhuang_point = -1;
		zhuang_id = "no zhuang";
	}	
	
	for(i=0; i<sizeof(inv); i++)
	{
		if( (int)inv[i]->query_temp("shaizi/bet_amount") > 0 &&  inv[i]->query("id") != zhuang_id)
		{
			if( (int)inv[i]->query_temp("shaizi/point") > zhuang_point )
			{//this player won.
				tell_room(this_object(), inv[i]->query("name")+"赢了"+chinese_number(inv[i]->query_temp("shaizi/bet_amount"))+"两银子。\n");
				total_bet -= 2*inv[i]->query_temp("shaizi/bet_amount");
				if(total_bet >= 0)
				{ 
					pay_player(inv[i], 2*inv[i]->query_temp("shaizi/bet_amount"));
				}
				else
				{
					tell_room(this_object(), "糟糕！有人在这里偷钱！"+inv[i]->query("name")+"赢的钱拿不到了。\n");
				}
			}
			else
			{//this player lost.
				tell_room(this_object(), inv[i]->query("name")+"输了"+chinese_number(inv[i]->query_temp("shaizi/bet_amount"))+"两银子。\n");
			}
		}
	}

	//now consider the zhuang-jia.
	if(zhuang && total_bet > 0)
	{
		tell_room(this_object(), "剩下的"+chinese_number(total_bet)+"两银子都是庄家"+zhuang->query("name")+"的了。\n");
		pay_player(zhuang, total_bet);
		total_bet = 0;
	}

	//finally, clear everything for players.
	for(i=0; i<sizeof(inv); i++)
	{
		if( inv[i]->query_temp("shaizi") ) inv[i]->delete_temp("shaizi");
	}
	game_status = 0;
	total_bet = 0;
	remove_call_out("check_finish");
}

void pay_player(object me, int total)
{
	object pay_cash, pay_gold, pay_silver;

	if(total/1000 > 0)
	{
		pay_cash = new("/obj/money/thousand-cash");
		pay_cash->set_amount (total/1000);
		total -= 1000*pay_cash->query_amount();

		pay_cash->move(me);
	}

	if(total/100 > 0)
	{
		pay_gold = new("/obj/money/gold");
		pay_gold->set_amount(total/100);
		total -= 100*pay_gold->query_amount();

		pay_gold->move(me);
	}

	pay_silver = new("/obj/money/silver");
	pay_silver->set_amount(total);
	if(total > 0)
	{
		pay_silver = new("/obj/money/silver");
		pay_silver->set_amount(total);
		total -= pay_silver->query_amount();

		pay_silver->move(me);
	}
}

int pay_out(object me, int total)
{//player pay money out, in unit of silver.
 //if sucessful return 1, else return 0.
 //what I did here is check all the money in silver the player has,
 //then destroy all his cash, gold, silver...then pay him back the difference.
	
	int diff;
	object cash, gold, silver;

	diff = check_silver(me) - total;	
	if( diff < 0 ) return 0; 
	//the player does not have enough money.

	//now destroy this players cash, gold and silver.
	cash = present("thousand-cash_money", me);
	gold = present("gold_money", me);
	silver = present("silver_money", me);
	if( cash ) destruct(cash);
	if( gold ) destruct(gold);
	if(silver) destruct(silver);

	//now pay his back the difference.	
	if( diff > 0 ) pay_player(me, diff);

	return 1;		
}

int check_silver(object me)
{//this function check the money in silver a player has,
	object cash, gold, silver;
	int total_silver;
	
	cash = present("thousand-cash_money", me);
	gold = present("gold_money", me);
	silver = present("silver_money", me);
	total_silver = 0;
	if( cash ) total_silver += 1000*(cash->query_amount());
	if( gold ) total_silver += 100*(gold->query_amount());
	if(silver) total_silver += (silver->query_amount());	

	return total_silver;
}


int do_look(string arg)
{
	object zhuang;
	object *inv = all_inventory(this_object());
	int i;
	object me = this_player();

	if(arg == "table")
	{
		if(total_bet > 0)
		{
			write("现在的赌注总共是"+total_bet+"两银子。\n");
			for(i=0; i<sizeof(inv); i++)
			{
				if( inv[i]->query_temp("shaizi/bet_amount") > 0 )
					write(inv[i]->query("name")+"："+inv[i]->query_temp("shaizi/bet_amount")+"两。\n");
			}

		}
		else write("现在还没有人下注。\n");

		if(zhuang_id == "no zhuang")
			write("目前还没有庄家。\n");
		else
		{
			if(objectp(zhuang=present(zhuang_id, this_object())) && living(zhuang) )
			{//if the zhuang-jia is here.
				write("目前的庄家是"+zhuang->query("name")+"("+zhuang->query("id")+")。\n");	
			}
			else 
			{
				write("庄家不知道跑到哪里去了。\n");
				zhuang_id = "no zhuang";
			}		
		}
		return 1;
	}
	return 0;	
}





